import 'package:flutter/material.dart';
import 'package:pp_uikit/date_picker/pp_base_picker.dart';
import 'package:pp_uikit/date_picker/pp_date_time_formatter.dart';
import 'package:pp_uikit/date_picker/pp_date_widget.dart';
import 'package:pp_uikit/date_picker/pp_time_widget.dart';
import 'package:pp_uikit/theme/pp_picker_theme.dart';

///时间选择模式枚举
enum PPDateTimePickerMode {
  /// 日期选择器
  date,

  /// 时间选择器
  time,
}

class PPDatePicker {
  static void show(
    BuildContext context, {
    /// 点击弹框外部区域能否消失
    bool? canBarrierDismissible,

    /// 能滚动到的最小日期
    DateTime? minDateTime,

    /// 能滚动到的最大日期
    DateTime? maxDateTime,

    /// 初始选择的时间。默认当前时间
    DateTime? initialDateTime,

    /// 时间格式化的格式
    String? dateFormat,

    /// 分钟间切换的差值
    int minuteDivider = 1,

    /// 时间选择组件显示的时间类型
    PPDateTimePickerMode pickerMode = PPDateTimePickerMode.date,

    /// 选中的样式
    TextStyle? itemTextSelectedStyle,

    /// 点击【取消】回调给调用方的回调事件
    DateVoidCallback? onCancel,

    /// 点击【完成】回调给调用方的数据
    DateVoidCallback? onClose,

    /// 时间滚动选择时候的回调事件
    DateValueCallback? onChange,

    /// 弹框点击外围消失的回调事件
    DateValueCallback? onConfirm,

    /// 主题色
    Color? themeColor,
  }) {
    // 处理时间范围
    minDateTime ??= DateTime.parse(datePickerMinDatetime);
    maxDateTime ??= DateTime.parse(datePickerMaxDatetime);

    // 初始化时间
    initialDateTime ??= DateTime.now();
    dateFormat = PPDateTimeFormatter.generateDateFormat(dateFormat, pickerMode);

    Navigator.of(context, rootNavigator: false)
        .push(
          _DatePickerRoute(
            canBarrierDismissible: canBarrierDismissible,
            minDateTime: minDateTime,
            maxDateTime: maxDateTime,
            initDateTime: initialDateTime,
            dateFormat: dateFormat,
            minuteDivider: minuteDivider,
            pickerMode: pickerMode,
            themeColor: themeColor,
            onCancel: onCancel,
            onChange: onChange,
            onConfirm: onConfirm,
            barrierLabel:
                MaterialLocalizations.of(context).modalBarrierDismissLabel,
            itemTextSelectedStyle: itemTextSelectedStyle,
          ),
        )
        .whenComplete(onClose ?? () {});
  }
}

class _DatePickerRoute<T> extends PopupRoute<T> {
  _DatePickerRoute({
    this.minDateTime,
    this.maxDateTime,
    this.initDateTime,
    this.minuteDivider,
    this.dateFormat,
    this.pickerMode = PPDateTimePickerMode.date,
    this.onCancel,
    this.onChange,
    this.onConfirm,
    this.barrierLabel,
    this.canBarrierDismissible,
    this.itemTextSelectedStyle,
    RouteSettings? settings,
    this.themeColor,
  });

  bool? canBarrierDismissible;

  final DateTime? minDateTime, maxDateTime, initDateTime;
  final String? dateFormat;
  final PPDateTimePickerMode pickerMode;
  final VoidCallback? onCancel;
  final DateValueCallback? onChange;
  final DateValueCallback? onConfirm;

  /// 选中的样式
  TextStyle? itemTextSelectedStyle;
  final int? minuteDivider;

  /// 主题色
  Color? themeColor;

  @override
  Color get barrierColor => Colors.black54;

  @override
  bool get barrierDismissible => canBarrierDismissible ?? true;

  @override
  String? barrierLabel;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    double height = PPPickerTheme.pickerHeight;
    height += PPPickerTheme.headerHeight;
    Widget bottomSheet = MediaQuery.removePadding(
      context: context,
      removeTop: true,
      child: _DatePickerComponent(route: this, pickerHeight: height),
    );

    return bottomSheet;
  }

  @override
  Duration get transitionDuration => const Duration(milliseconds: 200);
}

// ignore: must_be_immutable
class _DatePickerComponent extends StatelessWidget {
  final _DatePickerRoute route;
  final double _pickerHeight;

  const _DatePickerComponent({required this.route, required pickerHeight})
      : _pickerHeight = pickerHeight;

  @override
  Widget build(BuildContext context) {
    Widget? pickerWidget;
    switch (route.pickerMode) {
      case PPDateTimePickerMode.date:
        pickerWidget = PPDateWidget(
          minDateTime: route.minDateTime,
          maxDateTime: route.maxDateTime,
          initDateTime: route.initDateTime,
          dateFormat: route.dateFormat,
          onCancel: route.onCancel,
          onChange: route.onChange,
          onConfirm: route.onConfirm,
          itemTextSelectedStyle: route.itemTextSelectedStyle,
          themeColor: route.themeColor,
        );
        break;

      case PPDateTimePickerMode.time:
        pickerWidget = PPTimerWidget(
          minDateTime: route.minDateTime,
          maxDateTime: route.maxDateTime,
          initDateTime: route.initDateTime,
          dateFormat: route.dateFormat,
          onCancel: route.onCancel,
          onChange: route.onChange,
          onConfirm: route.onConfirm,
          themeColor: route.themeColor,
        );
        break;
      default:
    }

    return GestureDetector(
      child: AnimatedBuilder(
        animation: route.animation!,
        builder: (BuildContext context, Widget? child) {
          return ClipRect(
            child: CustomSingleChildLayout(
              delegate:
                  _BottomPickerLayout(route.animation!.value, _pickerHeight),
              child: PPPickerClipRRect(
                borderRadius: const BorderRadius.only(
                  topLeft: Radius.circular(PPPickerTheme.cornerRadius),
                  topRight: Radius.circular(PPPickerTheme.cornerRadius),
                ),
                child: pickerWidget,
              ),
            ),
          );
        },
      ),
    );
  }
}

class _BottomPickerLayout extends SingleChildLayoutDelegate {
  _BottomPickerLayout(this.progress, this.contentHeight);

  final double progress;
  final double contentHeight;

  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    return BoxConstraints(
      minWidth: constraints.maxWidth,
      maxWidth: constraints.maxWidth,
      minHeight: 0.0,
      maxHeight: contentHeight,
    );
  }

  @override
  Offset getPositionForChild(Size size, Size childSize) {
    double height = size.height - childSize.height * progress;
    return Offset(0.0, height);
  }

  @override
  bool shouldRelayout(_BottomPickerLayout oldDelegate) {
    return progress != oldDelegate.progress;
  }
}

/// Picker 顶端 圆角装饰类，参考系统 [ClipRRect]
class PPPickerClipRRect extends ClipRRect {
  const PPPickerClipRRect({
    Key? key,
    BorderRadius borderRadius = const BorderRadius.only(
      topLeft: Radius.circular(PPPickerTheme.cornerRadius),
      topRight: Radius.circular(PPPickerTheme.cornerRadius),
    ),
    Widget? child,
  }) : super(key: key, borderRadius: borderRadius, child: child);
}
